"""
示例任务函数
展示不同类型任务的实现方式
"""

import asyncio
import time
import random
import math
from typing import Optional
from app.core.task_scheduler import (
    ProgressContext,
    light_task,
    heavy_task,
    scheduled_task,
    periodic_task,
)

from loguru import logger


@light_task("simple_calculation", timeout=30)
async def simple_calculation(
    x: int = 15,
    y: int = 25,
    progress_ctx: Optional[ProgressContext] = None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> int:
    """简单计算任务"""
    logger.info(f"开始计算任务: {task_name} (ID: {task_id})")
    try:
        if progress_ctx:
            await progress_ctx.start(4, "开始计算...")
            await asyncio.sleep(1)

            await progress_ctx.add_step("参数验证", "验证输入参数")
            await asyncio.sleep(1)

            await progress_ctx.add_step("执行计算", f"计算 {x} + {y}")
            result = x + y
            await asyncio.sleep(1)

            await progress_ctx.add_step("结果验证", f"结果: {result}")
            await asyncio.sleep(1)

            await progress_ctx.complete(f"计算完成，结果: {result}")
        else:
            result = x + y
            await asyncio.sleep(1)
    except Exception as e:
        if progress_ctx:
            await progress_ctx.fail(f"计算失败: {str(e)}")

        logger.error(f"计算任务失败: {task_name} (ID: {task_id})")
        raise

    return result


@light_task("async_web_request", timeout=60)
async def async_web_request(
    url: str = "https://httpbin.org/delay/2",
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
    progress_ctx=None,
) -> dict:
    """异步网络请求任务"""
    try:
        if progress_ctx:
            await progress_ctx.start(4, "准备网络请求...")
            await asyncio.sleep(2)

            await progress_ctx.add_step("URL验证", f"验证URL: {url}")
            await asyncio.sleep(3)

            await progress_ctx.add_step("发送请求", "正在发送HTTP请求...")
            await asyncio.sleep(2)  # 模拟网络请求

            await progress_ctx.add_step("处理响应", "解析响应数据...")
            response_data = {
                "url": url,
                "status": 200,
                "response_time": "2.1s",
                "content_length": 1024,
            }
            await asyncio.sleep(3)

            await progress_ctx.complete("网络请求完成")
        else:
            await asyncio.sleep(2)
            response_data = {
                "url": url,
                "status": 200,
                "response_time": "2.0s",
                "content_length": 1024,
            }

        return response_data

    except Exception as e:
        if progress_ctx:
            await progress_ctx.fail(f"网络请求失败: {str(e)}")
        raise


@light_task("data_processing", timeout=120)
async def data_processing(
    data: list = [],
    progress_ctx=None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> dict:
    """数据处理任务"""
    if not data:
        data = list(range(1, 101))  # 默认数据

    if progress_ctx:
        await progress_ctx.start(5, "初始化数据处理...")
        await asyncio.sleep(2)

        await progress_ctx.add_step("数据验证", f"验证 {len(data)} 条数据")
        await asyncio.sleep(3)

        await progress_ctx.add_step("数据清洗", "清理和预处理数据")
        # 模拟数据清洗
        cleaned_data = [x for x in data if isinstance(x, (int, float))]
        await asyncio.sleep(5)

        await progress_ctx.add_step("数据转换", "执行数据转换操作")
        # 模拟数据转换
        transformed_data = [x * 2 + 1 for x in cleaned_data]
        await asyncio.sleep(5)

        await progress_ctx.add_step("结果统计", "生成统计信息")
        stats = {
            "original_count": len(data),
            "cleaned_count": len(cleaned_data),
            "transformed_count": len(transformed_data),
            "sum": sum(transformed_data),
            "avg": (
                sum(transformed_data) / len(transformed_data) if transformed_data else 0
            ),
            "max": max(transformed_data) if transformed_data else 0,
            "min": min(transformed_data) if transformed_data else 0,
        }
        await asyncio.sleep(3)

        await progress_ctx.complete(f"处理完成，共处理 {len(transformed_data)} 条数据")
    else:
        cleaned_data = [x for x in data if isinstance(x, (int, float))]
        transformed_data = [x * 2 + 1 for x in cleaned_data]
        stats = {
            "original_count": len(data),
            "cleaned_count": len(cleaned_data),
            "transformed_count": len(transformed_data),
            "sum": sum(transformed_data),
            "avg": (
                sum(transformed_data) / len(transformed_data) if transformed_data else 0
            ),
            "max": max(transformed_data) if transformed_data else 0,
            "min": min(transformed_data) if transformed_data else 0,
        }
        await asyncio.sleep(2)

    return stats


@heavy_task("cpu_intensive_calculation", timeout=300)
async def cpu_intensive_calculation(
    n: int = 100000,
    progress_ctx=None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> dict:
    """CPU密集型计算任务"""
    if progress_ctx:
        await progress_ctx.start(4, "开始CPU密集型计算...")
        await asyncio.sleep(0.1)

        await progress_ctx.add_step("初始化", f"准备计算 {n} 次迭代")

        # 分批计算，更新进度
        batch_size = n // 10
        total = 0

        for i in range(10):
            batch_start = i * batch_size
            batch_end = min((i + 1) * batch_size, n)

            # 执行批次计算
            batch_total = 0
            for j in range(batch_start, batch_end):
                batch_total += math.sqrt(j + 1) * math.sin(j) * math.cos(j)

            total += batch_total

            progress = ((i + 1) / 10) * 80 + 10  # 10% 到 90%
            await progress_ctx.set_progress(progress, f"计算批次 {i+1}/10 完成")
            await asyncio.sleep(0.1)  # 让出控制权

        await progress_ctx.add_step("结果汇总", f"计算总和: {total:.2f}")

        result = {
            "iterations": n,
            "result": total,
            "computation_type": "sqrt + sin + cos",
            "batches": 10,
        }

        await progress_ctx.complete(f"CPU计算完成，结果: {total:.2f}")
    else:
        total = 0
        for i in range(n):
            total += math.sqrt(i + 1) * math.sin(i) * math.cos(i)

        result = {
            "iterations": n,
            "result": total,
            "computation_type": "sqrt + sin + cos",
        }

    return result


@heavy_task("matrix_multiplication", timeout=600)
async def matrix_multiplication(
    size: int = 100,
    progress_ctx=None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> dict:
    """矩阵乘法任务"""
    if progress_ctx:
        await progress_ctx.start(5, "开始矩阵乘法计算...")
        await asyncio.sleep(0.1)

        await progress_ctx.add_step("矩阵生成", f"生成 {size}x{size} 矩阵")
        # 生成随机矩阵
        matrix_a = [[random.random() for _ in range(size)] for _ in range(size)]
        matrix_b = [[random.random() for _ in range(size)] for _ in range(size)]
        await asyncio.sleep(0.2)

        await progress_ctx.add_step("内存分配", "分配结果矩阵空间")
        result_matrix = [[0.0 for _ in range(size)] for _ in range(size)]
        await asyncio.sleep(0.1)

        await progress_ctx.add_step("矩阵乘法", "执行矩阵乘法运算")
        # 执行矩阵乘法，分批更新进度
        for i in range(size):
            for j in range(size):
                for k in range(size):
                    result_matrix[i][j] += matrix_a[i][k] * matrix_b[k][j]

            # 每完成一行更新进度
            if i % max(1, size // 20) == 0:  # 最多更新20次
                progress = 60 + (i / size) * 30  # 60% 到 90%
                await progress_ctx.set_progress(
                    progress, f"计算进度: {i+1}/{size} 行完成"
                )
                await asyncio.sleep(0.01)

        await progress_ctx.add_step("结果验证", "验证计算结果")
        # 计算一些统计信息
        total_sum = sum(sum(row) for row in result_matrix)
        max_val = max(max(row) for row in result_matrix)
        min_val = min(min(row) for row in result_matrix)
        await asyncio.sleep(0.2)

        result = {
            "matrix_size": f"{size}x{size}",
            "total_operations": size * size * size,
            "result_sum": total_sum,
            "result_max": max_val,
            "result_min": min_val,
        }

        await progress_ctx.complete(f"矩阵乘法完成 ({size}x{size})")
    else:
        # 简化版本
        matrix_a = [[random.random() for _ in range(size)] for _ in range(size)]
        matrix_b = [[random.random() for _ in range(size)] for _ in range(size)]
        result_matrix = [[0.0 for _ in range(size)] for _ in range(size)]

        for i in range(size):
            for j in range(size):
                for k in range(size):
                    result_matrix[i][j] += matrix_a[i][k] * matrix_b[k][j]

        total_sum = sum(sum(row) for row in result_matrix)
        max_val = max(max(row) for row in result_matrix)
        min_val = min(min(row) for row in result_matrix)

        result = {
            "matrix_size": f"{size}x{size}",
            "total_operations": size * size * size,
            "result_sum": total_sum,
            "result_max": max_val,
            "result_min": min_val,
        }

    return result


@scheduled_task("generate_daily_report", timeout=120)
async def generate_daily_report(
    date: Optional[str] = None,
    progress_ctx=None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> dict:
    """生成日报任务"""
    import datetime

    if not date:
        date = datetime.datetime.now().strftime("%Y-%m-%d")

    if progress_ctx:
        await progress_ctx.start(6, "开始生成日报...")
        await asyncio.sleep(0.1)

        await progress_ctx.add_step("数据收集", "收集当日数据")
        # 模拟数据收集
        await asyncio.sleep(0.5)

        await progress_ctx.add_step("数据分析", "分析业务指标")
        # 模拟数据分析
        metrics = {
            "total_tasks": random.randint(50, 200),
            "completed_tasks": random.randint(40, 180),
            "failed_tasks": random.randint(0, 20),
            "avg_duration": round(random.uniform(1.0, 10.0), 2),
        }
        await asyncio.sleep(0.8)

        await progress_ctx.add_step("图表生成", "生成统计图表")
        await asyncio.sleep(0.6)

        await progress_ctx.add_step("报告编写", "编写分析报告")
        report_content = f"""
        日期: {date}
        总任务数: {metrics['total_tasks']}
        完成任务数: {metrics['completed_tasks']}
        失败任务数: {metrics['failed_tasks']}
        平均执行时间: {metrics['avg_duration']}s
        成功率: {(metrics['completed_tasks']/metrics['total_tasks']*100):.1f}%
        """
        await asyncio.sleep(0.5)

        await progress_ctx.add_step("报告保存", "保存报告文件")
        await asyncio.sleep(0.3)

        result = {
            "date": date,
            "metrics": metrics,
            "report_content": report_content.strip(),
            "status": "completed",
        }

        await progress_ctx.complete(f"日报生成完成 ({date})")
    else:
        await asyncio.sleep(2)
        metrics = {
            "total_tasks": random.randint(50, 200),
            "completed_tasks": random.randint(40, 180),
            "failed_tasks": random.randint(0, 20),
            "avg_duration": round(random.uniform(1.0, 10.0), 2),
        }

        result = {"date": date, "metrics": metrics, "status": "completed"}

    return result


@periodic_task("system_health_check", timeout=60)
async def system_health_check(
    progress_ctx=None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> dict:
    """系统健康检查任务"""
    if progress_ctx:
        await progress_ctx.start(5, "开始系统健康检查...")
        await asyncio.sleep(0.1)

        await progress_ctx.add_step("CPU检查", "检查CPU使用率")
        cpu_usage = random.uniform(10, 80)
        await asyncio.sleep(0.3)

        await progress_ctx.add_step("内存检查", "检查内存使用率")
        memory_usage = random.uniform(30, 90)
        await asyncio.sleep(0.3)

        await progress_ctx.add_step("磁盘检查", "检查磁盘空间")
        disk_usage = random.uniform(20, 85)
        await asyncio.sleep(0.4)

        await progress_ctx.add_step("网络检查", "检查网络连接")
        network_status = "healthy" if random.random() > 0.1 else "warning"
        await asyncio.sleep(0.2)

        health_status = "healthy"
        if cpu_usage > 80 or memory_usage > 85 or disk_usage > 80:
            health_status = "warning"
        if cpu_usage > 90 or memory_usage > 95 or disk_usage > 90:
            health_status = "critical"

        result = {
            "timestamp": time.time(),
            "cpu_usage": round(cpu_usage, 1),
            "memory_usage": round(memory_usage, 1),
            "disk_usage": round(disk_usage, 1),
            "network_status": network_status,
            "overall_status": health_status,
        }

        await progress_ctx.complete(f"健康检查完成 - 状态: {health_status}")
    else:
        await asyncio.sleep(1)
        result = {
            "timestamp": time.time(),
            "cpu_usage": round(random.uniform(10, 80), 1),
            "memory_usage": round(random.uniform(30, 90), 1),
            "disk_usage": round(random.uniform(20, 85), 1),
            "network_status": "healthy",
            "overall_status": "healthy",
        }

    return result


# 长时间运行的任务示例
@heavy_task("long_running_task", timeout=600)
async def long_running_simulation(
    duration: int = 30,
    progress_ctx=None,
    task_id: Optional[str] = None,
    task_name: Optional[str] = None,
) -> dict:
    """长时间运行的模拟任务"""
    if progress_ctx:
        await progress_ctx.start(duration, f"开始 {duration} 秒模拟任务...")

        results = []
        for i in range(duration):
            # 模拟一些工作
            work_result = random.randint(1, 1000)
            results.append(work_result)

            await progress_ctx.set_progress(
                ((i + 1) / duration) * 100,
                f"第 {i+1}/{duration} 秒: 生成数据 {work_result}",
            )

            await asyncio.sleep(1)  # 等待1秒

        final_result = {
            "duration": duration,
            "total_results": len(results),
            "sum": sum(results),
            "average": sum(results) / len(results),
            "max": max(results),
            "min": min(results),
        }

        await progress_ctx.complete(f"模拟任务完成，耗时 {duration} 秒")
    else:
        results = []
        for i in range(duration):
            results.append(random.randint(1, 1000))
            await asyncio.sleep(1)

        final_result = {
            "duration": duration,
            "total_results": len(results),
            "sum": sum(results),
            "average": sum(results) / len(results),
            "max": max(results),
            "min": min(results),
        }

    return final_result
